package com.liuyk.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.os.Handler;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageView;

import com.liuyk.util.DeviceUtil;

/**
 * 可拖拽的GridView
 * <p/>
 * Created by Administrator on 2015/9/11.
 */
public class DragGridView extends GridView {
    private OnPositionChangerListener mOnPositionChangerListener;

    private final Handler mHandler = new Handler();
    private final Runnable mCreateDragRunnable = new Runnable() {
        @Override
        public void run() {
            createDragImage(mCreateX, mCreateY);
        }
    };

    private int mScrollBy = 20;
    private final Runnable mScrollDragRunnable = new Runnable() {
        @Override
        public void run() {
            smoothScrollBy(mScrollBy, 300);
            mHandler.postDelayed(mScrollDragRunnable, 300);
        }
    };

    private View mDownView;
    private Bitmap mDragBitmap;

    private final WindowManager mWindowManager;
    private WindowManager.LayoutParams mWindowLayoutParams;
    private ImageView mDragImageView;

    //触摸点相对于item的坐标值(自身)
    private int mItemX;
    private int mItemY;

    /**
     * 开始创建镜像时,镜像的XY位置
     */
    private int mCreateX;
    private int mCreateY;

    /**
     * 按下的位置
     */
    private int mDownItemPosition;

    /**
     * 是否可以拖拽
     */
    private boolean mDragEnabled;

    public DragGridView(Context context) {
        this(context, null);
    }

    public DragGridView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DragGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    }

    @Override
    public boolean onInterceptTouchEvent(@NonNull MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:

                int downX = (int) ev.getX();
                int downY = (int) ev.getY();
                mDownItemPosition = pointToPosition(downX, downY);

                //位置无效或者不允许拖拽,拦截手势事件
                if (mDownItemPosition == AdapterView.INVALID_POSITION || !mDragEnabled) {
                    return super.onInterceptTouchEvent(ev);
                }
                mDownView = getChildAt(mDownItemPosition - getFirstVisiblePosition());
                if (mDownView != null) {
                    //开启绘图机制
                    mDownView.setDrawingCacheEnabled(true);
                    //获取downView在缓存中的Bitmap对象
                    mDragBitmap = Bitmap.createBitmap(mDownView.getDrawingCache());
                    //释放缓存,避免重复出现镜像
                    mDownView.destroyDrawingCache();

                    //计算出触摸点相对于,自己本身的坐标值
                    mItemX = downX - mDownView.getLeft();
                    mItemY = downY - mDownView.getTop();

                    //计算出开始创建镜像时,镜像的位置
                    mCreateX = (int) ev.getRawX() - mItemX;
                    mCreateY = (int) ev.getRawY() - mItemY - DeviceUtil.getStatusHeight(getContext());
                    mHandler.post(mCreateDragRunnable);

                    //隐藏要拖动的Item
                    mDownView.setVisibility(View.INVISIBLE);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.i("touch", "InterceptTouch: " + "move");
                break;
            case MotionEvent.ACTION_UP:
                Log.i("touch", "InterceptTouch: " + "up");
                break;
            default:
                break;
        }
        return super.onInterceptTouchEvent(ev);//默认返回false
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent ev) {
        if (mDragEnabled && mDragImageView != null) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:

                    onMoveDrag((int) ev.getRawX(), (int) ev.getRawY());
                    int moveX = (int) ev.getX();
                    int moveY = (int) ev.getY();
                    swapItem(moveX, moveY);

                    break;
                case MotionEvent.ACTION_UP:
                    removeDragImage();
                    mHandler.removeCallbacks(mCreateDragRunnable);
                    mHandler.removeCallbacks(mScrollDragRunnable);
                    int toPositionX = (int) ev.getX();
                    int toPositionY = (int) ev.getY();
                    stopDrag(toPositionX, toPositionY);
                    break;
                default:
                    break;
            }
        }
        return super.onTouchEvent(ev);
    }

    private void onMoveDrag(int moveX, int moveY) {//移动镜像
        if (mDownView != null && mDragImageView != null) {

            int mOffsetY = moveY - mItemY - DeviceUtil.getStatusHeight(getContext());
            mWindowLayoutParams.x = moveX - mItemX;
            mWindowLayoutParams.y = mOffsetY;
            mWindowManager.updateViewLayout(mDragImageView, mWindowLayoutParams);

            //GridView自动滚动
            if(mOffsetY > (DeviceUtil.getWindowHeight(getContext()) * 0.5)){
                mScrollBy = 20;
                mHandler.postDelayed(mScrollDragRunnable, 300);
            } else if (mOffsetY < (DeviceUtil.getWindowHeight(getContext()) / 4)){
                mScrollBy = -20;
                mHandler.postDelayed(mScrollDragRunnable, 300);
            }

        }
    }

    private void swapItem(int toPositionX, int toPositionY) {
        int toItemPosition = pointToPosition(toPositionX, toPositionY);
        final View toItemView = getChildAt(toItemPosition - getFirstVisiblePosition());

        if (toItemPosition == mDownItemPosition || toItemPosition == AdapterView.INVALID_POSITION ||
                toItemView == null || mDownView == null || mOnPositionChangerListener == null) {
            return;
        }
        mOnPositionChangerListener.onChange(mDownItemPosition, toItemPosition);
        for (int i = 0; i < getChildCount(); i++) {
            getChildAt(i).setVisibility(View.VISIBLE);
        }
        toItemView.setVisibility(View.INVISIBLE);
        //关键的一步,每次到达一个新位置,一定要重新将开始位置和结束位置,致为一直
        //否则就会位置错乱
        mDownItemPosition = toItemPosition;

    }

    private void stopDrag(int toPositionX, int toPositionY) {
        int toItemPosition = pointToPosition(toPositionX, toPositionY);
        final View toItemView = getChildAt(toItemPosition - getFirstVisiblePosition());

        //交换位置
        if (mDownView != null && toItemView != null) {
            mOnPositionChangerListener.onChange(mDownItemPosition, toItemPosition);
        }
        //如果toItemView为null,也要把所有的child显示,否则会出现child丢失的现象
        for (int i = 0; i < getChildCount(); i++) {
            getChildAt(i).setVisibility(View.VISIBLE);
        }

    }

    private void createDragImage(int createX, int createY) {
        mWindowLayoutParams = new WindowManager.LayoutParams();
        mWindowLayoutParams.format = PixelFormat.TRANSLUCENT;//图片之外的区域透明
        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.START;
        mWindowLayoutParams.alpha = 0.6f;
        mWindowLayoutParams.x = createX;
        mWindowLayoutParams.y = createY;
        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;

        mDragImageView = new ImageView(getContext());
        mDragImageView.setImageBitmap(mDragBitmap);
        mWindowManager.addView(mDragImageView, mWindowLayoutParams);
    }

    private void removeDragImage() {//移除镜像
        if (mDragImageView != null) {
            mWindowManager.removeView(mDragImageView);
            mDragImageView = null;
        }
    }

    /**
     * 设置是否可以拖拽
     *
     * @param isDrag 是否拖拽
     */
    public void setDragEnabled(boolean isDrag) {
        this.mDragEnabled = isDrag;
    }

    /**
     * 得到mDragEnabled
     *
     * @return mDragEnabled
     */
    public boolean getDragEnabled() {
        return mDragEnabled;
    }

    public void setOnPositionChangerListener(OnPositionChangerListener onPositionChangerListener) {
        this.mOnPositionChangerListener = onPositionChangerListener;
    }

    public interface OnPositionChangerListener {
        void onChange(int fromPosition, int toPosition);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return super.drawChild(canvas, child, drawingTime);
    }
}
